package javabase.demo03;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolPractice {
    public static void main(String[] args) {
        // 1. ThreadPoolExecutor七大参数
        demonstrateThreadPoolExecutor();

        // 2. 常见线程池
        demonstrateCommonPools();

        // 3. 线程池工作流程
        demonstrateThreadPoolWorkflow();

        // 4. 拒绝策略
        demonstrateRejectionPolicies();

        // 5. 线程工厂
        demonstrateThreadFactory();

        // 6. 定时任务线程池
        demonstrateScheduledThreadPool();
    }

    private static void demonstrateThreadPoolExecutor() {
        System.out.println("\n=== ThreadPoolExecutor七大参数 ===");

        // 1. 核心线程数
        int corePoolSize = 2;
        // 2. 最大线程数
        int maximumPoolSize = 4;
        // 3. 空闲线程存活时间
        long keepAliveTime = 10;
        // 4. 时间单位
        TimeUnit unit = TimeUnit.SECONDS;
        // 5. 工作队列
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        // 6. 线程工厂
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        // 7. 拒绝策略
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize, maximumPoolSize, keepAliveTime, unit,
                workQueue, threadFactory, handler);

        System.out.println("线程池创建成功");
        System.out.println("核心线程数: " + corePoolSize);
        System.out.println("最大线程数: " + maximumPoolSize);
        System.out.println("队列容量: " + workQueue.remainingCapacity());

        executor.shutdown();
    }

    private static void demonstrateCommonPools() {
        System.out.println("\n=== 常见线程池 ===");

        // 1. FixedThreadPool - 固定大小线程池
        ExecutorService fixedPool = Executors.newFixedThreadPool(3);
        System.out.println("FixedThreadPool: 固定3个线程");

        // 2. CachedThreadPool - 可缓存线程池
        ExecutorService cachedPool = Executors.newCachedThreadPool();
        System.out.println("CachedThreadPool: 根据需要创建新线程");

        // 3. SingleThreadExecutor - 单线程线程池
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        System.out.println("SingleThreadExecutor: 单个线程顺序执行");

        // 4. ScheduledThreadPool - 定时任务线程池
        ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
        System.out.println("ScheduledThreadPool: 可安排任务在给定延迟后运行或定期执行");

        // 使用示例
        for (int i = 0; i < 5; i++) {
            final int taskId = i;
            fixedPool.execute(() -> {
                System.out.println("FixedPool任务" + taskId + "执行于: " +
                        Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        // 关闭线程池
        fixedPool.shutdown();
        cachedPool.shutdown();
        singleThreadPool.shutdown();
        scheduledPool.shutdown();
    }

    private static void demonstrateThreadPoolWorkflow() {
        System.out.println("\n=== 线程池工作流程 ===");

        // 创建一个小型线程池演示工作流程
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, // 核心线程数
                3, // 最大线程数
                1, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2), // 容量为2的队列
                new ThreadPoolExecutor.CallerRunsPolicy() // 调用者运行策略
        );

        System.out.println("提交6个任务，观察线程池行为:");
        System.out.println("核心线程:2, 最大线程:3, 队列容量:2");

        for (int i = 1; i <= 6; i++) {
            final int taskId = i;
            try {
                executor.execute(() -> {
                    System.out.println("任务" + taskId + "执行于: " +
                            Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000); // 模拟任务执行
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
                System.out.println("提交任务" + taskId + "成功");
            } catch (Exception e) {
                System.out.println("提交任务" + taskId + "失败: " + e.getMessage());
            }
        }

        executor.shutdown();
    }

    private static void demonstrateRejectionPolicies() {
        System.out.println("\n=== 拒绝策略 ===");

        // 1. AbortPolicy - 默认策略，抛出RejectedExecutionException
        testRejectionPolicy(new ThreadPoolExecutor.AbortPolicy(), "AbortPolicy");

        // 2. CallerRunsPolicy - 由调用线程执行该任务
        testRejectionPolicy(new ThreadPoolExecutor.CallerRunsPolicy(), "CallerRunsPolicy");

        // 3. DiscardPolicy - 直接丢弃任务
        testRejectionPolicy(new ThreadPoolExecutor.DiscardPolicy(), "DiscardPolicy");

        // 4. DiscardOldestPolicy - 丢弃队列中最旧的任务，然后重试
        testRejectionPolicy(new ThreadPoolExecutor.DiscardOldestPolicy(), "DiscardOldestPolicy");
    }

    private static void testRejectionPolicy(RejectedExecutionHandler policy, String policyName) {
        System.out.println("\n测试拒绝策略: " + policyName);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                1, 1, 0, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), policy);

        // 提交3个任务，但线程池只能处理2个（1个执行，1个排队）
        for (int i = 1; i <= 3; i++) {
            final int taskId = i;
            try {
                executor.execute(() -> {
                    System.out.println(policyName + " - 任务" + taskId + "执行于: " +
                            Thread.currentThread().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
                System.out.println(policyName + " - 提交任务" + taskId + "成功");
            } catch (Exception e) {
                System.out.println(policyName + " - 提交任务" + taskId + "失败: " + e.getMessage());
            }
        }

        executor.shutdown();
    }

    private static void demonstrateThreadFactory() {
        System.out.println("\n=== 线程工厂 ===");

        // 自定义线程工厂
        ThreadFactory customFactory = new CustomThreadFactory("CustomThread");

        ExecutorService executor = new ThreadPoolExecutor(
                2, 2, 0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                customFactory);

        for (int i = 0; i < 3; i++) {
            executor.execute(() -> {
                System.out.println("任务执行于: " + Thread.currentThread().getName());
            });
        }

        executor.shutdown();
    }

    // 自定义线程工厂
    static class CustomThreadFactory implements ThreadFactory {
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        CustomThreadFactory(String namePrefix) {
            this.namePrefix = namePrefix + "-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
            t.setDaemon(false);
            t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
    private static void demonstrateScheduledThreadPool() {
        System.out.println("\n=== 定时任务线程池 ===");

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

        // 1. 延迟执行
        System.out.println("提交延迟任务: " + new java.util.Date());
        scheduler.schedule(() -> {
            System.out.println("延迟任务执行: " + new java.util.Date());
        }, 2, TimeUnit.SECONDS);

        // 2. 固定速率执行
        System.out.println("提交固定速率任务: " + new java.util.Date());
        scheduler.scheduleAtFixedRate(() -> {
            System.out.println("固定速率任务执行: " + new java.util.Date());
        }, 1, 2, TimeUnit.SECONDS);

        // 3. 固定延迟执行
        System.out.println("提交固定延迟任务: " + new java.util.Date());
        scheduler.scheduleWithFixedDelay(() -> {
            System.out.println("固定延迟任务开始: " + new java.util.Date());
            try {
                Thread.sleep(1000); // 模拟任务执行时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("固定延迟任务结束: " + new java.util.Date());
        }, 1, 2, TimeUnit.SECONDS);

        // 10秒后关闭调度器
        scheduler.schedule(() -> {
            System.out.println("关闭调度器");
            scheduler.shutdown();
        }, 10, TimeUnit.SECONDS);
    }
}
